package com.jzo2o.orders.manager.handler;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.enums.RefundStatusEnum;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.orders.base.enums.OrderRefundStatusEnum;
import com.jzo2o.orders.base.mapper.OrdersMapper;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.base.model.domain.OrdersRefund;
import com.jzo2o.orders.manager.service.IOrdersRefundService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Component
@Slf4j
public class OrdersHandler {

    @Resource
    private IOrdersRefundService ordersRefundService;

    @Resource
    private RefundRecordApi refundRecordApi;

    @Resource
    private OrdersMapper ordersMapper;

    //解决同级方法调用，事务失效问题
    @Resource
    private OrdersHandler ordersHandler;

    @XxlJob("handleRefundOrders")
    public void handleRefundOrders() {

        // 1-查询当前退款中的订单数据(目前是有退款中的就在这个表，当退款成功就把数据删除)
        List<OrdersRefund> ordersRefunds = ordersRefundService.queryRefundOrderListByCount(10);
        if (CollectionUtil.isEmpty(ordersRefunds)) {
            log.error("退款中数据为空，无需操作");
            return;
        }

        // 2-遍历订单，逐个退款
        for (OrdersRefund ordersRefund : ordersRefunds) {
            requestRefundOrder(ordersRefund);
        }
    }

    /**
     * 调用支付系统(支付底层会调用微信)发起退款
     * @param ordersRefund      退款记录
     */
    private void requestRefundOrder(OrdersRefund ordersRefund) {

        // 1-发起第三方退款调用
        ExecutionResultResDTO executionResultResDTO = null;
        try {
            executionResultResDTO = refundRecordApi.refundTrading(ordersRefund.getTradingOrderNo(), ordersRefund.getRealPayAmount());
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 2-判断是否退款成功
        if (ObjectUtils.isEmpty(executionResultResDTO)) {
            log.error("发起退款失败，请稍后重试");
            return;
        }

        // 3-更新退款状态
        ordersHandler.refundOrder(ordersRefund, executionResultResDTO);

    }

    @Transactional
    public void refundOrder(OrdersRefund ordersRefund, ExecutionResultResDTO executionResultResDTO) {
        //根据响应结果更新退款状态
        int refundStatus = OrderRefundStatusEnum.REFUNDING.getStatus();//退款中
        if (ObjectUtil.equal(RefundStatusEnum.SUCCESS.getCode(), executionResultResDTO.getRefundStatus())) {
            //退款成功
            refundStatus = OrderRefundStatusEnum.REFUND_SUCCESS.getStatus();
        } else if (ObjectUtil.equal(RefundStatusEnum.FAIL.getCode(), executionResultResDTO.getRefundStatus())) {
            //退款失败
            refundStatus = OrderRefundStatusEnum.REFUND_FAIL.getStatus();
        }

        //如果是退款中状态，程序结束
        if (ObjectUtil.equal(refundStatus, OrderRefundStatusEnum.REFUNDING.getStatus())) {
            return;
        }

        //非退款中状态，更新订单的退款状态
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<Orders>()
                .eq(Orders::getId, ordersRefund.getId())
                .ne(Orders::getRefundStatus, refundStatus)
                .set(Orders::getRefundStatus, refundStatus)
                .set(ObjectUtil.isNotEmpty(executionResultResDTO.getRefundId()), Orders::getRefundId, executionResultResDTO.getRefundId())
                .set(ObjectUtil.isNotEmpty(executionResultResDTO.getRefundNo()), Orders::getRefundNo, executionResultResDTO.getRefundNo());
        int rows = ordersMapper.update(null, updateWrapper);
        //非退款中状态，删除申请退款记录，删除后定时任务不再扫描
        if(rows>0){
            //非退款中状态，删除申请退款记录，删除后定时任务不再扫描
            ordersRefundService.removeById(ordersRefund.getId());
        }
    }

    /**
     * 新启动一个线程请求退款
     * @param ordersRefundId
     */
    public void requestRefundNewThread(Long ordersRefundId){
        //启动一个线程请求第三方退款接口
        new Thread(()->{
            //查询退款记录
            OrdersRefund ordersRefund = ordersRefundService.getById(ordersRefundId);
            if(ObjectUtil.isNotNull(ordersRefund)){
                //请求退款
                requestRefundOrder(ordersRefund);
            }
        }).start();
    }
}
